package Git2024_5_22;

public class Validation_1 {
    //全局异常处理器
    /**
     * @RestControllerAdvice 类级别-组合注解
     * @ExceptionHandler 方法级别
     */
    //POJO-VO-DTO
    /**
     * 1.参数前@Validated
     * 2.在属性上添加校验注解
     */
    //非POJO
    /**
     * 声明参数方式接收
     * 1.在类上添加@Validated
     * 2.在参数前添加校验注解
     */
/*----------------------------------------------------正课-------------------------------------------------------*/
    // SpringMVC拦截器
    /**
     * SpringMVC提供的组件

     * 作用:拦截请求和响应
     *     集成包含相同权限校验的功能 简化代码
     *     例如 某平台的100个功能 有60个功能都需要校验用户登陆状态 若每个功能中都写相同的校验逻辑 代码冗余
     *  1.拦截请求: 在控制器之前适配器与控制器连接处可以进行拦截
     *            逻辑: &&逻辑 一层拦截器不过关该请求即会被打回
     *  2.拦截响应: 在控制器执行完逻辑之后 返回 Model And View 时进行拦截响应
     *            或在前端控制器将渲染完的前端页面传给客户端时将响应拦截 做最终的校验

     * 应用场景[了解]:
     *  权限验证 如登陆验证 进入处理器检测是否登录 若未登录直接返回登录界面
     *  日志记录 记录请求信息的日志 以便于进行信息监控 信息统计等
     *  性能监控[分析慢请求,优化逻辑] 系统莫名高负载 可通过拦截器在进入控制器之前记录开始时间 在处理完后记录结束时间 从而得到该请求的处理时间

     * 特性
     *  拦截 拦截信息
     *  过滤 对拦截到的信息进行统一处理
     *  放行 信息验证通过


  - 拦截器工程创建
     * 创建拦截器工程时只需勾选Spring Web依赖即可

     * 拦截器的使用流程
     *  1.创建拦截器的类 至少有三个方法对应三个拦截点
     *  2.注册拦截器 配置拦截器的拦截策略
     *  3.测试拦截器


     *1* 创建拦截器的类
     * 1.拦截器不需要通过注解声明 而需要实现HandlerInterceptor接口作为其实现类
        implements HandlerInterceptor
     * 该接口中包含三个方法
        preHandle 拦截请求,返回值为boolean型  [能决定拦截对象的逻辑是否结束]
        postHandle 拦截控制器的响应  [只能拦截做处理 不能决定该拦截对象逻辑能否结束]
        afterCompletion 拦截前端控制器的最终响应  [只能拦截做处理 不能决定该拦截对象逻辑能否结束]
     * 2.实现类作为HandlerInterceptor接口的实现类需要重写上述三个方法

     *2* 注册拦截器
       1.创建配置类 通过注解标记为配置类
       2.实现`WebMvcConfigurer`接口 --- 标准化配置接口
       3.重写`添加拦截器[addInterceptors]`方法 --- addI + tab键补齐
     *   3.1 public void addInterceptors(InterceptorRegistry registry) {}
     *   3.2 在方法体中用该方法的参数打点调用方法以添加拦截器对象 --- 将创建的拦截器类对象作为参数传入
     *   3.3.1 此时该方法代表添加了一个拦截器对象
     *   3.3.2 且添加了一个默认拦截策略1 --- 因为未指定任何拦截器的具体拦截内容
             registry.addInterceptor(new MyInterceptor1());
     *   3.4 拦截策略2:`添加拦截路径`以指定少量请求 --- 不同路径之间用`,`隔开
             registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/users/login","/users/reg");
     *   3.5 拦截策略3:拦截指定模块的请求 比如拦截用户模块["/users/"]的所有请求
             使用拦截器中的通配符 `**` 不同路径之间用`,`隔开即可 若要规定具体功能 将路径补全或新写一个路径皆可
             registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/users/**","/weibo/**");
     *   3.6 拦截策略4:排除指定模块的部分请求,比如:拦截用户模块的所有请求 但是排除/users/login请求
             registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/users/**").excludePathPatterns("/users/login");
     */
    /**
     * 当请求发送过来时 Tomcat会封装用户信息到容器里 该容器中包含了几乎所有的用户信息 例如请求的url地址 请求头 请求体 请求行等
     * 而会话也作为信息的一种储存在其中 因此可以借用HttpServletRequest类的对象request打点的方法单独获取会话信息进行是否登录的校验
     * request.getSession()
     */
    /**
     * 当存在多组(每组拦截器有三个方法对应三个拦截点)拦截器时 请求每经过一个拦截点 就需要执行所有拦截器的对应拦截点方法 只有所有拦截器都准许放行
     * 该请求才能继续执行流程 直到最后返回给客户端
     */
    /*
            list1:[pre1    pre2    pre3]
            list2:[post1   post2   post3]
            list3:[after1  after2  after3]

            dataStructure 结构

            这些拦截器的方法会被分类储存在不同的集合中(如上) 第一个方法preHandle调用顺序为拦截器添加顺序
            即根据集合下标进行执行调用
            而postHandle afterCompletion方法的调用 是按照集合下标从大到小执行的 也就是从最后注册的
            拦截器开始向前遍历输出这些方法

            通过源码可知

            查看源码步骤[拦截器]
            1.IDEA 中按住 ctrl + n 出现搜索框
            2.输入 DispatcherServlet
            3.右上角下载源
            4.点击左侧品字型图标 Structure
            5.找到 DoDispatch() 方法
            6.从上到下查看此方法
            7.依次进入到 preHandle postHandle afterCompletion 中查看源码
         */
    /*---------------------------------------------------AOP---------------------------------------------------------*/
    /**
     * AOP
     * 设计思想 面向切面编程 <-> OOP 面向对象编程
     * AOP是对OOP的补充完善
     *  OOP是比较静态的过程
     *  AOP是偏向动态的过程:在运行过程中,不改变原代码的基础之上,动态植入一些扩展功能或控制对象执行
     *
     * 环境准备
     * 1.工程及接口创建 不勾选任何依赖 需要手动添加
     * 2.需求:打印较为详细的日志 帮助排错和分析
     *      产生问题:`非核心业务逻辑代码`和`核心业务逻辑代码`耦合度较高
     *             代码冗余 计算逻辑,结构相似
     *      解决思路: 为目标类创建子类或兄弟类 对目标业务进行功能拓展 --- 不改变核心逻辑代码 符合OCP原则:对扩展开放 对修改关闭
     *      产生问题: 只能扩展业务简单的项目 否则工作量极大
     * 引入 AOP
     * JDK官方提供的API Proxy为目标类创建子类或兄弟类
     * CGLIB 为目标类创建子类或兄弟类
     */
    /**
     * 1.手动添加依赖
     */
    /*
            <!--引入aop依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>
     */
    /**
     * 2.创建指定类作为切面类用于拓展新功能
         2.1 通过@Aspect标识该类为切面类 (类级别注解)
             切面类的本质为拦截
         2.2 通过@Component将该类交由Spring Framework管理
     */
    // 注解
    /**
     * @Before(value="execution()") 前置通知 在执行目标方法之前执行
     * 例如:
     * @Before(value = "execution(public int cn.tedu._07springaop.aop.CalculatorImpl.*(..))")
     *      execution() 切入点表达式
     *      public int 权限标识符
     *      cn.tedu._07springaop.aop.CalculatorImpl.*(..) 方法表达类型[具体路径]
     *         * 方法名随意 表示拦截所有路径下的指定方法
     *        (..) 参数列表随意
     *      调用方法时会被拦截: 系统会先扫描有没有切面类 若有 进行拦截 结合切面类的逻辑完成后续操作
     */

/**
 * **手动添加Spring AOP依赖说明**
 *
 *
 *
 * **创建切面类以实现功能拓展**
 *
 * 1. **定义切面类**: 使用`@Aspect`注解标记该类为切面类，此注解在类级别上使用，表明该类具有拦截和扩展业务逻辑的能力。
 *
 * 2. **组件管理**: 应用`@Component`注解，确保Spring框架能够识别并管理这个切面类，使其能够参与到Spring的Bean生命周期中。
 *
 * **前置通知使用示例**
 *
 *
 * - `@Before`: 表示在目标方法执行前执行的通知。
 * - `execution()`: 是切入点表达式，用于定义哪些方法的执行将被此通知影响。
 *   - `public int`: 指定匹配的方法的访问权限为公共（public）且返回类型为整型（int）。
 *   - `cn.tedu._07springaop.aop.CalculatorImpl.*(..)`:
 *       - `*`: 表示任意方法名，意味着所有方法都将被此切面关注。
 *       - `..`: 表示任意数量和类型的参数，即不关心方法的具体参数。
 *
 * **工作原理简述**:
 * 当调用匹配到的计算器方法时，系统首先检查是否存在相关的切面逻辑。如果存在，则先执行`@Before`标注的前置通知逻辑，之后再执行原方法逻辑，从而达到在核心业务逻辑执行前后拓展或修改行为的目的。
 */

}
